package Peripherals;

import java.io.PrintStream;
import java.util.Scanner;

import DataFormatConversionComponents.NumberConverter;
import StorageComponents.Memory;

/**
 * This class manages the AR2RISC IO components 
 *
 */
public class IODeviceController {
	
	private KeyBoard keyBoard;
	private Monitor monitor;
	
	public IODeviceController(){
		keyBoard = new KeyBoard();
		monitor = new Monitor();
	}
	
	/**
	 * This method ensures that the system accepts a valid input from the keyboard. 
	 * A valid input will have at least one digit, and will not exceed 2 digits, and those digit's 
	 * decimal equivalent > 127 && < 256 in order to access the data segment only
	 * @return string (the input hex number)
	 */
	public String getKeyBoardInput(){
		System.out.println( "Please enter one letter or character: " );
		String input = keyBoard.read();
		NumberConverter converter = new NumberConverter();
		int inputInteger = converter.stringToASCII(input);  		
		boolean inputReady; 	
		//analyze the input at least once
		do{												
			//if a letter or character was no entered
			if( inputInteger < 33 || inputInteger > 126 ){
				inputReady = false;
				System.out.println( "INCORRECT SELECTION" );
				System.out.println( "The input is not a letter or character. Please enter one letter or character: " );
				input = keyBoard.read();
				inputInteger = converter.stringToASCII(input);
			} else if( input.length() > 1 ){
				inputReady = false;
				System.out.println( "INCORRECT SELECTION" );
				System.out.println( "The input has more than one letter or character. Please enter one letter or character: " );
				input = keyBoard.read();
				inputInteger = converter.stringToASCII(input);
			}
			else{
				//input is ready
				inputReady = true;
			}
		}while( !inputReady ); //loop if input is not ready
		
		return input;
	}
	/**
	 * This method displays all data stored in main memory from address 252-255
	 * @param mainMemory our AR2RISC's main memory
	 */
	public void displayMonitorContent(Memory mainMemory){
		Object[] display = new Object[4];
		for(int i = 252, j = 0; i <= 255; i++, j++ )
			//retrieve the 8 bits that are in every address corresponding to the display peripheral
			display[j] = mainMemory.readByte(i);
		monitor.displayContent(display);
	}
	/**
	 * Inner class that simulates a keyboard. Simply uses a Scanner object to read from the keyboard in real-time
	 * 
	 *
	 */
	private class KeyBoard{

		private Scanner in;
		private String input;
		
		public KeyBoard(){
			this.in = new Scanner(System.in);
		}
		
		public String read(){
			return in.next();
		}
		
	}
	/** This inner class handles the Monitor or Display component
	 * 
	 */
	private class Monitor{
		/**
		 * This method is used to display data from memory with addresses corresponding to the monitor peripheral port
		 * which in fact is all data with address >= 252 && address  <= 255
		 * @param display array that contains the data from memory that corresponds to the display port (address >= 252 && address <= 255)
		 */
		public void displayContent(Object[] display){		
			NumberConverter converter = new NumberConverter();
			System.out.println("DISPLAY:");
			for( int i = 0; i <  display.length; i++ ){
				int[] d = (int[]) display[i];
				System.out.print( converter.ASCIIToChar( converter.binaryToDecimal( d ) ) + " ");
			}
		}
	}

}